# -*- coding: utf_8 -*-
# @Create   : 2021/8/30 10:19
# @Author   : yh
# @Remark   : 巡检计划db层
import logging
import time
from typing import List

from mxsoftpy import DB
from mxsoftpy.exception import DBError, ParamsError, DataError

from db.common.VideoManage.VideoQuality.conf import TaskCycleDB
from utils.conf.mxconfig import MxConfig
from utils.public.time_process import stamp_2_date


class InspectionPlanDB(DB):
    def _expot_data(self,data):
        """
        转换成导出excl所需格式
        """
        data_dict = {
                "header": "巡视计划",
                "headline": {
                    "plan_code": "序号",
                    "name": "计划名称",
                    "task_cycle_name": "计划周期",
                    "begin_time": "开始时间",
                    "principal": "负责人",
                    "data_state": "状态",
                },
                "data": data
        }
        file_name = "plan_" + str(int(time.time())) + ".xlsx"
        return data_dict,file_name

    def __plan_name_duplicate_check(self, name: str, code: str = None):
        """
        巡检任务名称校验
        """
        self.tree.open('VideoQuality', 'InspectionPlan', file='IOT')
        res_list = self.tree.filter(name=name, state=1)[1]
        if res_list and res_list[0] != code:
            raise ParamsError("%s计划名称已存在" % name)

    def create_or_update_items(self, plan_code: str, items: List[dict]) -> bool:
        """
        添加巡检计划内的检测项目
        :param plan_code: 巡检计划code
        :param items: 检测项目详情
            eg:
                [
                    {
                        "item_code": 1,
                        "confidence": 50
                    },
                    {
                        "item_code": 2,
                        "confidence": 30
                    }
                ]
        """
        try:
            self.tree.open('VideoQuality', 'InspectionPlan\\%s\\TestItems' % plan_code, file='IOT')
            self.tree.delete()
        except DBError:
            pass
        finally:
            self.tree.open('VideoQuality', 'InspectionPlan\\%s\\TestItems' % plan_code, file='IOT', path_flag=True)
        for item in items:
            self.tree.insert_key_items([('test_code', item['test_code']), ('confidence', item['confidence'])])
        return True

    def create(self, **kwargs) -> str:
        """
        添加巡检计划
        """
        self.__plan_name_duplicate_check(kwargs['name'])
        code = self.tree.open('VideoQuality', 'InspectionPlan', file='IOT'
                              ).insert_key_items([(k, v) for k, v in kwargs.items()])
        logging.info('添加了一个巡检计划，计划code：%s, 计划内容如下：' % code)
        logging.info(str(kwargs))
        return code

    def update(self, plan_code: str, **kwargs):
        """
        更新巡检计划
        :param plan_code: 要更新的计划code
        """

        self.__plan_name_duplicate_check(kwargs['name'], plan_code)
        self.tree.open('VideoQuality', 'InspectionPlan\\%s' % plan_code, file='IOT'
                       ).insert_items([(k, v) for k, v in kwargs.items()])
        logging.info('更新了一个巡检计划, 计划code: %s, 更新内容如下: ' % plan_code)
        logging.info(str(kwargs))
        return plan_code

    def delete(self, del_list: List[str]) -> List[str]:
        """
        删除巡检计划
        :param del_list: 要删除的计划列表
        """
        for del_key in del_list:
            self.tree.open('VideoQuality', 'InspectionPlan\\%s' % del_key, file='IOT', host=MxConfig.HOST,
                           port=MxConfig.PORT).insert_items([('state', 0), ('update_time', int(time.time()))])

            logging.info('删除了一个巡检计划, 计划code：%s' % del_key)

        return del_list

    def stop(self, stop_list: List[str]) -> List[str]:
        """
        停用巡检计划
        :param stop_list: 要停用的计划列表
        """
        from db.common.VideoManage.VideoQuality.inspection_task import InspectionTaskDB
        for stop_key in stop_list:
            self.tree.open('VideoQuality', 'InspectionPlan\\%s' % stop_key, file='IOT', host=MxConfig.HOST,
                           port=MxConfig.PORT).insert_items([('data_state', 0), ('update_time', int(time.time()))])
            logging.info('将一个巡检计划状态设为停用, 计划code：%s' % stop_key)
        _, task_keys = self.tree.open('VideoQuality', 'InspectionTask', file='IOT', host=MxConfig.HOST, port=MxConfig.PORT)\
            .filter(inspection_plan_code__in=stop_list, task_state='0')
        for stop_task in task_keys:
            InspectionTaskDB().delete(stop_task)

        return stop_list

    def start_check(self, start_list: List[str]) -> List[dict]:
        """
        启用巡检计划校验
        :param start_list: 要启用的计划列表
        """
        res_list = list()
        res_dict = dict()
        self.tree.open('VideoQuality', 'InspectionPlan', file='IOT', host=MxConfig.HOST,port=MxConfig.PORT)
        plan_dict = self.tree.sub_items(start_list,['videos'])
        self.tree.open('VideoQuality', 'Video', file='IOT', host=MxConfig.HOST, port=MxConfig.PORT)
        for key, videos in plan_dict.items():
            res_dict['plan_code'] = key
            res_dict['start_type'] = 0
            video_list = videos.get('videos').split(';')
            _, videos = self.tree.filter(state=0)     # 判断计划视频源是否删除
            for video in video_list:
                if video in videos:
                    res_dict['start_type'] = 1
                    break
            res_list.append(res_dict)

        return res_list

    def start(self, start_list: List[str]) -> List[str]:
        """
        启用巡检计划
        :param start_list: 要启用的计划列表
        """
        for start_key in start_list:
            self.tree.open('VideoQuality', 'InspectionPlan\\%s' % start_key, file='IOT', host=MxConfig.HOST,
                           port=MxConfig.PORT).insert_items([('data_state', 1), ('update_time', int(time.time()))])

            logging.info('将一个巡检计划状态设为启用, 计划code：%s' % start_key)

        return start_list

    def select(self, **kwargs) -> tuple:
        """
        获取巡检计划列表
        """
        total, keys = self.tree.open('VideoQuality', 'InspectionPlan', file='IOT', host=MxConfig.HOST,
                                     port=MxConfig.PORT).filter(**kwargs)

        sub_items = self.tree.sub_items(key_list=keys, prop_list=['name', 'task_cycle_code', 'begin_time', 'principal',
                                                                  'data_state','videos']) if keys else dict()

        task_cycle = TaskCycleDB('TaskCycle').list(['name', 'state'])

        res = dict()
        res['data'] = list()
        for key in keys:  # 保持排序、以及添加字段
            sub_items[key].update({'plan_code': key,
                                   'task_cycle_name': task_cycle[sub_items[key]['task_cycle_code']]['name']
                                   if task_cycle.get(sub_items[key]['task_cycle_code']) else ''})
            sub_items[key]['begin_time'] = stamp_2_date(sub_items[key]['begin_time'])
            res['data'].append(sub_items[key])

        return total, res

    def simple_list(self, **kwargs) -> dict:
        """
        返回在用的巡检计划列表（简单展示，不进行分页、连表查询name等功能）
        :param kwargs: 自定义查询条件
        """
        keys = self.tree.open('VideoQuality', 'InspectionPlan', file='IOT', host=MxConfig.HOST,
                              port=MxConfig.PORT).filter(state=1, **kwargs)[1]
        res_dict = self.tree.sub_items(key_list=keys) if keys else dict()

        return res_dict

    def retrieve(self, plan_code: str) -> dict:
        """
        获取计划详情
        """
        from db.common.VideoManage.VideoQuality.conf import round_test_items
        try:
            self.tree.open('VideoQuality', 'InspectionPlan\\%s' % plan_code, file='IOT')
        except DBError as e:
            logging.error('获取单个巡检巡检详情时出错：打开code %s失败，错误详情：%s' % (plan_code, str(e)))
            raise DataError('获取巡检计划详情失败')
        item_dict = self.tree.items()
        item_dict['begin_time'] = stamp_2_date(item_dict['begin_time']).split(" ")[0]
        item_dict['create_time'] = stamp_2_date(item_dict['create_time'])
        item_dict['update_time'] = stamp_2_date(item_dict['update_time'])
        try:
            self.tree.open('VideoQuality', 'InspectionPlan\\%s\\TestItems' % plan_code, file='IOT')
        except DBError as e:
            logging.error('获取单个巡检巡检详情时出错：打开code %s失败，错误详情：%s' % (plan_code, str(e)))
            raise DataError('获取巡检计划详情失败')

        item_dict["TestItems"] = round_test_items(self.tree.sub_items())

        return item_dict
